package xyz.hubery.util;

import lombok.SneakyThrows;
import org.jose4j.json.JsonUtil;
import org.jose4j.jwa.AlgorithmConstraints;
import org.jose4j.jwk.RsaJsonWebKey;
import org.jose4j.jws.AlgorithmIdentifiers;
import org.jose4j.jws.JsonWebSignature;
import org.jose4j.jwt.JwtClaims;
import org.jose4j.jwt.consumer.JwtConsumer;
import org.jose4j.jwt.consumer.JwtConsumerBuilder;

import java.security.PrivateKey;
import java.security.PublicKey;
import java.util.HashMap;
import java.util.Map;

public class JwtUtils {
  // 私钥
  public final static String PRIVATE_JSON = "{\"kty\":\"RSA\",\"n\":\"2cjqU6pthUsCnz2D97LINPlkb2fY1bkS6xc-FjQMsd_WhXf7wMWmcRBNrNZqbuY6PQMh2g1sWHCxuxRg7nyJfVSyPm6dYLTlw0NTzwjP32tUDTYQXZnALXPUTpRywGGxRhkJ8AGav6KFUgCVSEslCZd7h5WHdPHm7VZ9Nd5ea6yZdhIzLxOgj_tb3I4S7U-2EUAP8wEfdu4cJts3I2LHfLk4PmZG4zlfTo1E5d7DYfTPWT47vEFzqBtJIWD3kjnm3ge8XSM-lW5U_SV1N4Sn2wlw3hEYQoA-CWtCM2ekkk_9yj3J0Z_eBSr8MUW41XTA7Vmb9SMe241VKDSzkdN2tw\",\"e\":\"AQAB\",\"d\":\"KBfN08M_UFejzu8DOXmHVAFJlRzYFVhx_CeWPX4tjB16H64cAbwhTRVER3pds7bcp9jIxZzNAmcUwS0aPy1cHl-WRNoWTPRgjBb7-dRUeHwIyDnYv3KLp5J4VlML4RDbEt2PL8kL1RW1V4hV8y4qTl691hMYEdZqvey7NkyOs2GG8W8Kxg4g3nbphBqTXNDJ8jZ38kMbk-1mJCedP4iw600Blk2MEwA7bvaFmQDrTEaqApz197jPyhfVft5iFRli-wI0Xhu6Ija2y-Z_CiZwqxYYonrqiS97cbrYB-kZQ4QtY9w3iVD3M-uSs-7peXptJl6ATyEBurZ9viCXyM1G0Q\",\"p\":\"-vLM_esnqqOJXUzARYdtFl8NlHr5wBV3Jn7y56Buld6HYKcXnd7tTbik6RQe0bWRS_Og-zk4cuYzoxz8XzBQ878Vqc7EYlAeTERdbvRsjEq9YBowKJvLaHcpJkIbsi7cZqTU7eHpry6K7O8Jd4SMswAEyKgLEkFLoNI7R0JQrlk\",\"q\":\"3is23CrNHFZqJNxQxgxRtQqwunjVfdQQ1X-OJSKfpmzn62x2501oxJngXmAoHrdGShnzN3VVL_hsRbEib_OAK-oF4eq7c9BWvSZpHab676w_K63XnvSZR4flxZFStjilCAGJohVtZJDXuTUWkAcstC119ELcJxbN0jK-oPdeS48\",\"dp\":\"8xlIieZGm-AmjrJuRCyn-ZcFMcRbsr9YmHs8VjQtTJOws2nK0A2H9tWbM4thO6fXZCtT1GqfC3eDqEzJEnFcynNeygvaZJ7Wau2DUZwIl3NDtxhHdN9Pkhh1TXGXIOqSagDdoMBLv3-n51S86AIIxtKKz9MyPnHwkI94C1Trkak\",\"dq\":\"bO_Vo5ldH6MDwvVAqgvKWLJYO-caD-vXIUi9Y1oZ3FoUUizKFNqxH42wJbaSlZUaYyVcS_o9fhsaxAV6NFi6pU3H-qHFrqEelvrpmf-Rlcno47sHOksHibqKIRkD7JPT4BwY56AIFsKq9IaifJb4BZUw_Ed4ebZFz-bP8E-7LeM\",\"qi\":\"1R0Q6kvdgAvSwDKZnyPs-irUiJT6GAUmZwInLpAwWMAIBBsnXqLz8QtNzWOmZN88X0FzI57dvWiFuV5M2gbxBlSRKVuNH7xzL51d2sflH0QQxKbJGLWsjjd9lOFLfs_J-zTbeA6a-_7Jqs4_93XbmTPx3puXaSBYZobav6SFOH8\"}";
  // 公钥
  public final static String PUBLIC_JSON = "{\"kty\":\"RSA\",\"n\":\"2cjqU6pthUsCnz2D97LINPlkb2fY1bkS6xc-FjQMsd_WhXf7wMWmcRBNrNZqbuY6PQMh2g1sWHCxuxRg7nyJfVSyPm6dYLTlw0NTzwjP32tUDTYQXZnALXPUTpRywGGxRhkJ8AGav6KFUgCVSEslCZd7h5WHdPHm7VZ9Nd5ea6yZdhIzLxOgj_tb3I4S7U-2EUAP8wEfdu4cJts3I2LHfLk4PmZG4zlfTo1E5d7DYfTPWT47vEFzqBtJIWD3kjnm3ge8XSM-lW5U_SV1N4Sn2wlw3hEYQoA-CWtCM2ekkk_9yj3J0Z_eBSr8MUW41XTA7Vmb9SMe241VKDSzkdN2tw\",\"e\":\"AQAB\"}";


  /**
   * 生成token
   *
   * @param userId    用户id
   * @param username 用户名字
   * @return
   */
  @SneakyThrows
  public static String sign(Long userId, String username) {
    // 1、 创建jwtclaims  jwt内容载荷部分
    JwtClaims claims = new JwtClaims();
    // 是谁创建了令牌并且签署了它
    claims.setIssuer("hubery");
    // 令牌将被发送给谁
    claims.setAudience("audience");
    // 失效时间长 （分钟）
    claims.setExpirationTimeMinutesInTheFuture(60 * 24);
    // 令牌唯一标识符
    claims.setGeneratedJwtId();
    // 当令牌被发布或者创建现在
    claims.setIssuedAtToNow();
    // 再次之前令牌无效
    claims.setNotBeforeMinutesInThePast(2);
    // 主题
    claims.setSubject("shopping");
    // 可以添加关于这个主题得声明属性
    claims.setClaim("userId", userId);
    claims.setClaim("username", username);


    // 2、签名
    JsonWebSignature jws = new JsonWebSignature();
    //赋值载荷
    jws.setPayload(claims.toJson());


    // 3、jwt使用私钥签署
    PrivateKey privateKey = new RsaJsonWebKey(JsonUtil.parseJson(PRIVATE_JSON)).getPrivateKey();
    jws.setKey(privateKey);


    // 4、设置关键 kid
    jws.setKeyIdHeaderValue("keyId");


    // 5、设置签名算法
    jws.setAlgorithmHeaderValue(AlgorithmIdentifiers.RSA_USING_SHA256);
    // 6、生成jwt
    String jwt = jws.getCompactSerialization();
    return jwt;
   }




  /**
   * 解密token，获取token中的信息
   *
   * @param token
   */
  @SneakyThrows
  public static Map<String, Object> verify(String token){
    // 1、引入公钥
    PublicKey publicKey = new RsaJsonWebKey(JsonUtil.parseJson(PUBLIC_JSON)).getPublicKey();
    // 2、使用jwtcoonsumer  验证和处理jwt
    JwtConsumer jwtConsumer = new JwtConsumerBuilder()
         .setRequireExpirationTime() //过期时间
         .setAllowedClockSkewInSeconds(30) //允许在验证得时候留有一些余地 计算时钟偏差  秒
         .setRequireSubject() // 主题生命
         .setExpectedIssuer("hubery") // jwt需要知道谁发布得 用来验证发布人
         .setExpectedAudience("audience") //jwt目的是谁 用来验证观众
         .setVerificationKey(publicKey) // 用公钥验证签名  验证密钥
         .setJwsAlgorithmConstraints(new AlgorithmConstraints(AlgorithmConstraints.ConstraintType.WHITELIST, AlgorithmIdentifiers.RSA_USING_SHA256))
         .build();
    // 3、验证jwt 并将其处理为 claims
    try {
      JwtClaims jwtClaims = jwtConsumer.processToClaims(token);
      return jwtClaims.getClaimsMap();
     }catch (Exception e){
      return new HashMap();
     }
   }




  public static void main(String[] args){
    // 生成
    String baizhan = sign(1001L, "hubery");
    System.out.println(baizhan);


    Map<String, Object> stringObjectMap = verify(baizhan);
    System.out.println(stringObjectMap.get("userId"));
    System.out.println(stringObjectMap.get("username"));
   }
}
